package com.lx.algorithm.Tree;

import java.util.ArrayList;

/**
 * Description: 判断一棵树是不是 搜索二叉树
 * Copyright:   Copyright (c)2019
 * Company:     zefu
 *
 * @author: 张李鑫
 * @version: 1.0
 * Create at:   2021-10-18 17:39:01
 * <p>
 * Modification History:
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2021-10-18     张李鑫                     1.0         1.0 Version
 */
public class IsSearchTree {


    static class Node<T> {
        int value;
        Node left;
        Node right;

        public Node(int value) {
            this.value = value;
        }
    }

    public static class Info {
        int max;
        int min;
        boolean isIST;

        public Info(int max, int min, boolean isIST) {
            this.max = max;
            this.min = min;
            this.isIST = isIST;
        }
    }


    /**
     * 搜索二叉树:
     * 二叉树的每一个节点的左边节点都比头节点小
     * 二叉树的每一个节点的右边节点都比头节点大
     */


    public static boolean isSearchTree(Node node) {
        if (node == null) {
            return true;
        }
        return process1(node).isIST;

    }

    public static Info process1(Node node) {
        if (node == null) {
            return null;
        }
        Info leftInfo = process1(node.left);
        Info rightInfo = process1(node.right);
        int max = node.value;
        int min = node.value;
        boolean ist = true;

        if (leftInfo != null) {
            min = leftInfo.min;
            ist = (leftInfo.max < node.value)&&(leftInfo.isIST);
        }
        if (rightInfo != null) {
            max = rightInfo.max;
            ist = (ist) && (rightInfo.min > node.value)&&(rightInfo.isIST);
        }

        return new Info(max, min, ist);

    }

    /**
     * <p>
     * 中序遍历打印节点。
     * 遍历打印的节点查看是否全部为递增状态 即可判断当前树是否是搜索二叉树
     * </p>
     *
     * @param head
     * @return boolean
     * @Author zlx
     * @date 2021/10/19
     */
    public static boolean isBST1(Node head) {
        if (head == null) {
            return true;
        }
        ArrayList<Node> arr = new ArrayList<>();
        in(head, arr);
        for (int i = 1; i < arr.size(); i++) {
            if (arr.get(i).value <= arr.get(i - 1).value) {
                return false;
            }
        }
        return true;
    }

    public static void in(Node head, ArrayList<Node> arr) {
        if (head == null) {
            return;
        }
        in(head.left, arr);
        arr.add(head);
        in(head.right, arr);
    }

    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }


    public static void main(String[] args) {
        int maxLevel = 4;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (isBST1(head) != isSearchTree(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }


}
